package thread;
// 生产者消费者模式 （阻塞队列）
public class MessageQueue {
    // 实现阻塞队列
    // 方式 1 ： 循环链表
    // 方式 2 ： 循环数组（相对好实现）
    private int[] items;
    private volatile int head;
    private volatile int tail;
    private volatile int size;

    public MessageQueue() {
        this.items = new int[20];
        this.head = 0;
        this.tail = 0;
        this.size = 0;
    }

    // 向循环队列中 放元素
    public void put(int val) throws InterruptedException {
        synchronized(this){
            while(size == items.length) {
                this.wait();
            }
            items[tail++] = val;

            if(tail == items.length){
                tail = 0;
            }
            size++;
            this.notifyAll();
        }
    }

    public int take() throws InterruptedException {
        synchronized (this){
            while(size == 0){
                this.wait();
            }
            int ret = items[head];
            head++;
            if(head == items.length){
                head = 0;
            }
            size--;
            this.notifyAll();
            return ret;
        }
    }




    public static void main(String[] args) throws InterruptedException {
        MessageQueue queue = new MessageQueue();
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                for(int i = 0; i < 400; i++){
                    try {
                        queue.put(i);
                        System.out.println(Thread.currentThread().getName() + "生产 元素 :" + i);
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        },"生产者 1号 ");

        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    while(true){
                        int val = queue.take();
                        System.out.println(Thread.currentThread().getName() +"消费 元素 :"+ val);
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"消费者 1号 ");

        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    while(true){
                        int val = queue.take();
                        System.out.println(Thread.currentThread().getName() + "消费 元素 :"+ val);
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"消费者 2号 ");

        thread.start();
        thread1.start();
        thread2.start();
        thread.join();
        thread1.join();
        thread2.join();

    }

}
